package pers.vankid.timecount;

import com.google.common.base.Strings;
import pers.vankid.common.utils.excel.ExcelExport;
import pers.vankid.common.utils.excel.ExcelUtil;
import pers.vankid.timecount.model.TimeUnit;
import pers.vankid.timecount.model.stencil.*;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by shixj on 2018/4/19.
 */
public class Countor {

    public static void main(String[] args) {
        try {
            List<WorkDay> list = getSource();
            List<ErrorDay> listError = getErrorSource();
            Map<String,ErrorDay>errorDayMap=new HashMap<>();

            listError.stream().forEach(errorDay -> {
                if(!errorDayMap.containsKey(errorDay.getNum()+errorDay.getDate()))
                    errorDayMap.put(errorDay.getNum(),errorDay);
            });

            Map<String, Double> balanceMap=getLastBalanceMap();
            Map<String, FullMonth> resMap = new HashMap<>();
            list.stream().forEach(workDay -> {
                FullMonth fullMonth;
                String num = workDay.getNum();
                if (resMap.containsKey(num))
                    fullMonth = resMap.get(num);
                else {
                    fullMonth = new FullMonth();
                    fullMonth.setName(workDay.getName());
                    if(balanceMap.containsKey(workDay.getName()))
                    fullMonth.setLastBalance(balanceMap.get(workDay.getName()));
                    resMap.put(num, fullMonth);
                }
                setBalance(fullMonth, workDay,errorDayMap.get(workDay.getNum()+workDay.getDate()));
            });
            ExcelExport excelExport = setMonth(list.get(0), resMap);
            write(excelExport);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main1(String[] args) {
        try {
            List<WorkDay> list = getSource();
            Map<String, Double> balanceMap=getLastBalanceMap();
            Map<String, FullMonth> resMap = new HashMap<>();
            list.stream().forEach(workDay -> {
                FullMonth fullMonth;
                String num = workDay.getNum();
                if (resMap.containsKey(num))
                    fullMonth = resMap.get(num);
                else {
                    fullMonth = new FullMonth();
                    fullMonth.setName(workDay.getName());
                    if(balanceMap.containsKey(workDay.getName()))
                        fullMonth.setLastBalance(balanceMap.get(workDay.getName()));
                    resMap.put(num, fullMonth);
                }
                setBalance(fullMonth, workDay,null);
            });
            ExcelExport excelExport = setMonth(list.get(0), resMap);
            write(excelExport);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 自动选择日历模版
     *
     * @param workDay
     * @param resMap
     * @return
     * @throws Exception
     */
    private static ExcelExport setMonth(WorkDay workDay, Map<String, FullMonth> resMap) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = simpleDateFormat.parse(workDay.getDate());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int maxDay = calendar.getActualMaximum(Calendar.DATE);
        List<Month> details = new ArrayList<>();
        ExcelExport excelExport = null;
        switch (maxDay) {
            case 30:
                for (String key : resMap.keySet()) {
                    details.add(new CommonMonth().factory(resMap.get(key)));
                }
                excelExport = new ExcelExport("加班调休记录", CommonMonth.COLUMNS, "加班调休记录", details, null);
                break;
            case 31:
                for (String key : resMap.keySet()) {
                    details.add(new FullMonth().factory(resMap.get(key)));
                }
                excelExport = new ExcelExport("加班调休记录", FullMonth.COLUMNS, "加班调休记录", details, null);
                break;
            case 28:
                for (String key : resMap.keySet()) {
                    details.add(new CommonFebruary().factory(resMap.get(key)));
                }
                excelExport = new ExcelExport("加班调休记录", CommonFebruary.COLUMNS, "加班调休记录", details, null);
                break;
            case 29:
                for (String key : resMap.keySet()) {
                    details.add(new LeapFebruary().factory(resMap.get(key)));
                }
                excelExport = new ExcelExport("加班调休记录", LeapFebruary.COLUMNS, "加班调休记录", details, null);
                break;
        }
        return excelExport;
    }


    /**
     * 获取上月结余
     * @return
     * @throws Exception
     */
    private static Map<String, Double> getLastBalanceMap() throws Exception {
        Map<String, Double> map = new HashMap<>();
        String pathname = "C:" + File.separator + "2.txt"; // 绝对路径或相对路径都可以，这里是绝对路径，写入文件时演示相对路径
        File filename = new File(pathname); // 要读取以上路径的input。txt文件
        InputStreamReader reader = new InputStreamReader(
                new FileInputStream(filename)); // 建立一个输入流对象reader
        BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
        String line = "";
        while (line != null) {
            line = br.readLine(); // 一次读入一行数据
            if (!Strings.isNullOrEmpty(line)) {
                line = line.replace("\u0000", "").replace(" ", "")
                        .replace("\t", "");
                if (!line.isEmpty()) {
                    boolean minus=false;
                    if(line.contains("-")){
                        line=line.replace("-","");
                        minus=true;
                    }



                    String name = subByRegex(line, "[\\u4e00-\\u9fa5]+(?=[\\d+\\.?\\d+])", 0);
                    double lastBalance = Double.valueOf(line.replace(name, ""));;
                    if(minus)
                        lastBalance =-1*lastBalance;
                    map.put(name, lastBalance);
                }
            }
        }
        reader.close();
        return map;
    }


    /**
     * 获取原始数据
     *
     * @return
     * @throws Exception
     */
    private static List<WorkDay> getSource() throws Exception {
        File f = new File("C:" + File.separator + "1.xls");
        InputStream in = new FileInputStream(f);
        String fileExtension = "xlsx";
        Map<String, Integer> map = new HashMap<>();
        map.put("group", 0);
        map.put("num", 1);
        map.put("name", 2);
        map.put("date", 6);
        map.put("remark", 15);
        return ExcelUtil.transferExcelToEntity(2, fileExtension, in, map, null, WorkDay.class);

    }
    /**
     * 获取原始数据
     *
     * @return
     * @throws Exception
     */
    private static List<ErrorDay> getErrorSource() throws Exception {
        File f = new File("C:" + File.separator + "2.xls");
        InputStream in = new FileInputStream(f);
        String fileExtension = "xlsx";
        Map<String, Integer> map = new HashMap<>();
        map.put("num", 1);
        map.put("name", 2);
        map.put("date", 3);
        map.put("timeLong", 14);
        map.put("remark", 15);
        map.put("errorRemark", 16);
        return ExcelUtil.transferExcelToEntity(2, fileExtension, in, map, null, ErrorDay.class);

    }
    private static void write(ExcelExport excelExport) {
        if (excelExport != null)
            try {
                FileOutputStream fs = new FileOutputStream("C:" + File.separator + "result.xls");
                BufferedOutputStream bos = new BufferedOutputStream(fs);
                bos.write(ExcelUtil.export(excelExport));  //write()方法可以写入byte数组、int
                fs.close();
                bos.flush();
                bos.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

    public static String subByRegex(String sourceStr, String regex, int index) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(sourceStr);
        String res = "";
        if (matcher.find()) {
            res = matcher.group(index);
        }

        return res;
    }

    /**
     * 半小时计算 未满按半小时计算
     *
     * @param minutes
     * @return
     */
    private static double timeTransferUp(int minutes) {
        int res = minutes / 30;//取整
        int extra = minutes % 30;
        if (extra > 0)
            res++;
        return (double) res / 2;
    }

    /**
     * 半小时计算 未满不计算
     *
     * @param minutes
     * @return
     */
    private static double timeTransferLow(int minutes) {
        int res = minutes / 30;//取整
        return (double) res / 2;
    }

    private static void setBalance(FullMonth fullMonth, WorkDay workDay,ErrorDay errorDay) {
        try {
            TimeUnit timeUnit = new TimeUnit(workDay.getDate());
            String remark = workDay.getRemark().replace(":", "");
            int overtime = 0;
            int lieu = 0;
            if (remark.contains("加班"))
                overtime = Integer.valueOf(subByRegex(remark, "(?<=加班)(\\d)+(?=[分钟])", 0));

            double res;
            if(errorDay!=null&&!Strings.isNullOrEmpty(errorDay.getErrorRemark())&&errorDay.getErrorRemark().contains("调休"))
                         res=timeTransferLow(overtime)-Double.valueOf(errorDay.getTimeLong());
            else {
                if (remark.contains("迟到"))
                    lieu = Integer.valueOf(subByRegex(remark, "(?<=迟到)(\\d)+(?=[分钟])", 0));
                res=timeTransferLow(overtime) - timeTransferUp(lieu);;
            }

            switch (timeUnit.getDay()) {
                case 1:
                    fullMonth.setOne(res);
                    break;
                case 2:
                    fullMonth.setTwo(res);
                    break;
                case 3:
                    fullMonth.setThree(res);
                    break;
                case 4:
                    fullMonth.setFour(res);
                    break;
                case 5:
                    fullMonth.setFive(res);
                    break;
                case 6:
                    fullMonth.setSix(res);
                    break;
                case 7:
                    fullMonth.setSeven(res);
                    break;
                case 8:
                    fullMonth.setEight(res);
                    break;
                case 9:
                    fullMonth.setNine(res);
                    break;
                case 10:
                    fullMonth.setTen(res);
                    break;
                case 11:
                    fullMonth.setEleven(res);
                    break;
                case 12:
                    fullMonth.setTwelve(res);
                    break;
                case 13:
                    fullMonth.setThirteen(res);
                    break;
                case 14:
                    fullMonth.setFourteen(res);
                    break;
                case 15:
                    fullMonth.setFifteen(res);
                    break;
                case 16:
                    fullMonth.setSixteen(res);
                    break;
                case 17:
                    fullMonth.setSeventeen(res);
                    break;
                case 18:
                    fullMonth.setEighteen(res);
                    break;
                case 19:
                    fullMonth.setNineteen(res);
                    break;
                case 20:
                    fullMonth.setTwenty(res);
                    break;
                case 21:
                    fullMonth.setTwentyOne(res);
                    break;
                case 22:
                    fullMonth.setTwentyTwo(res);
                    break;
                case 23:
                    fullMonth.setTwentyThree(res);
                    break;
                case 24:
                    fullMonth.setTwentyFour(res);
                    break;
                case 25:
                    fullMonth.setTwentyFive(res);
                    break;
                case 26:
                    fullMonth.setTwentySix(res);
                    break;
                case 27:
                    fullMonth.setTwentySeven(res);
                    break;
                case 28:
                    fullMonth.setTwentyEight(res);
                    break;
                case 29:
                    fullMonth.setTwentyNine(res);
                    break;
                case 30:
                    fullMonth.setThirty(res);
                    break;
                case 31:
                    fullMonth.setThirtyOne(res);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
